#include <string.h>

const char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

// 将二进制数据 bindata 编码成 base64
// bindata: 源二进制数据
// binlength: 源二进制数据长度
// base64: 目标字符串，存储 base64 编码结果
// 返回值：指向目标字符串的指针
char * base64_encode( const unsigned char * bindata, int binlength, char * base64 )
{
    int i, j;
    unsigned char current;

    // 遍历源二进制数据，每次处理 3 个字节
    for ( i = 0, j = 0 ; i < binlength ; i += 3 )
    {
        // 第一个 base64 字符：取 bindata[i] 的高 6 位
        current = (bindata[i] >> 2) ;
        current &= (unsigned char)0x3F;
        base64[j++] = base64char[(int)current];

        // 第二个 base64 字符：取 bindata[i] 的低 2 位，bindata[i+1] 的高 4 位
        current = ( (unsigned char)(bindata[i] << 4 ) ) & ( (unsigned char)0x30 ) ;
        if ( i + 1 >= binlength )
        {
            base64[j++] = base64char[(int)current];
            base64[j++] = '=';
            base64[j++] = '=';
            break;
        }
        current |= ( (unsigned char)(bindata[i+1] >> 4) ) & ( (unsigned char) 0x0F );
        base64[j++] = base64char[(int)current];

        // 第三个 base64 字符：取 bindata[i+1] 的低 4 位，bindata[i+2] 的高 2 位
        current = ( (unsigned char)(bindata[i+1] << 2) ) & ( (unsigned char)0x3C ) ;
        if ( i + 2 >= binlength )
        {
            base64[j++] = base64char[(int)current];
            base64[j++] = '=';
            break;
        }
        current |= ( (unsigned char)(bindata[i+2] >> 6) ) & ( (unsigned char) 0x03 );
        base64[j++] = base64char[(int)current];

        // 第四个 base64 字符：取 bindata[i+2] 的低 6 位
        current = ( (unsigned char)bindata[i+2] ) & ( (unsigned char)0x3F ) ;
        base64[j++] = base64char[(int)current];
    }
    
    // 添加字符串结束符
    base64[j] = '\0';
    return base64;
}


// 解码 base64 编码的字符串为二进制数据
// base64：源字符串
// bindata: 存储解码后的二进制数据
// 返回值：解码后的二进制数据长度
int base64_decode( const char * base64, unsigned char * bindata )
{
    int i, j;
    unsigned char k;
    unsigned char temp[4];

    // 循环遍历 base64 编码的源字符串，每次处理 4 个字符
    for ( i = 0, j = 0; base64[i] != '\0' ; i += 4 )
    {
        // 清空临时数组 temp
        memset( temp, 0xFF, sizeof(temp) );

        // 从 base64 字符映射表中查找对应字符的索引，填充到 temp 数组
        for ( k = 0 ; k < 64 ; k ++ )
        {
            if ( base64char[k] == base64[i] )
                temp[0]= k;
        }
        for ( k = 0 ; k < 64 ; k ++ )
        {
            if ( base64char[k] == base64[i+1] )
                temp[1]= k;
        }
        for ( k = 0 ; k < 64 ; k ++ )
        {
            if ( base64char[k] == base64[i+2] )
                temp[2]= k;
        }
        for ( k = 0 ; k < 64 ; k ++ )
        {
            if ( base64char[k] == base64[i+3] )
                temp[3]= k;
        }

        // 解码第一个字节：取 temp[0] 的高 6 位
        bindata[j++] = ((unsigned char)(((unsigned char)(temp[0] << 2))&0xFC)) |
                ((unsigned char)((unsigned char)(temp[1]>>4)&0x03));
        if ( base64[i+2] == '=' )
            break;

        // 解码第二个字节：取 temp[1] 的低 4 位，temp[2] 的高 2 位
        bindata[j++] = ((unsigned char)(((unsigned char)(temp[1] << 4))&0xF0)) |
                ((unsigned char)((unsigned char)(temp[2]>>2)&0x0F));
        if ( base64[i+3] == '=' )
            break;

        // 解码第三个字节：取 temp[2] 的低 2 位，temp[3] 的所有位
        bindata[j++] = ((unsigned char)(((unsigned char)(temp[2] << 6))&0xF0)) |
                ((unsigned char)(temp[3]&0x3F));
    }
    
    // 返回解码后的二进制数据长度
    return j;
}



/*
编码（Encoding）和解码（Decoding）的核心思想是通过一定的规则将原始数据转换为另一种表示形式，
以便在不同系统或环境中传输、存储或处理数据。在你提供的代码中，使用了 Base64 编码和解码的核心思想。

Base64 编码是一种将二进制数据转换为可打印字符的编码方式。
它的核心思想是将原始二进制数据分割成固定长度（通常是3字节）的块，
然后将每个块中的数据转换为可打印字符的表示，例如字母、数字和一些特殊字符。
编码过程中涉及到位运算和位掩码，以及字符映射表，最终生成的 Base64 编码字符串在不损失数据的情况下可以被传输和存储。

解码过程则是对编码后的字符串进行逆操作，将Base64编码的字符串恢复成原始的二进制数据。
解码器会根据Base64编码规则，逆向操作进行位运算和还原，
将每个Base64字符还原成对应的二进制数据块，最终合并这些块以得到原始的二进制数据。

Base64 编码和解码的核心思想在于将二进制数据转换为一组有限字符，以适应特定需求，
例如传输数据时需要可打印字符的限制，或者在 URL、XML 等上下文中需要避免特殊字符的问题。
虽然 Base64 增加了数据的长度，但它能够在多种环境中可靠地传输和处理二进制数据。
*/